package com.kexin.fpay.api;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.kexin.common.config.WebAppConfigurer;
import com.kexin.common.user.service.IConfigDataService;
import com.kexin.common.utils.ApplicationContextUtil;
import com.kexin.common.utils.HttpURLRequestUtils;
import com.kexin.fpay.config.FPayConfig;

/**
 * 聚合支付
 * @author ao
 */
public class FPayApi {

	static Logger log = LoggerFactory.getLogger(FPayApi.class);

	/**
	 * 公共请求参数
	 * @return
	 */
	private static Map<String, Object> getHeader() {
		Date nowDate = new Date();
		Map<String, Object> header = new HashMap<String, Object>();
		header.put("appId", FPayConfig.getAppId());
		header.put("channelType", FPayConfig.getChannelType());
		header.put("outReqDate", DateFormatUtils.format(nowDate, "yyyy-MM-dd"));
		header.put("outReqTime", DateFormatUtils.format(nowDate, "HH:mm:ss"));
		header.put("version", FPayConfig.getVersion());
		return header;
	}

	/**
	 * 获取token
	 * @return
	 */
	public static String getAuthorization(boolean isCache) {
		log.info("调用聚合支付获取token接口");
		IConfigDataService configDataService = ApplicationContextUtil.getConfigDataService();
		String authorizationToken = null;
		if (isCache) {
			authorizationToken = configDataService.getValue("authorizationToken");
		}
		String authorization = null;
		if (StringUtils.isNotEmpty(authorizationToken)) {
			try {
				JSONObject tokenData = JSONObject.parseObject(authorizationToken);
				String time = tokenData.getString("time");
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				Date date = sdf.parse(time);
				
				Calendar calendar = Calendar.getInstance();
				calendar.add(Calendar.HOUR, -11);
				if (calendar.getTime().before(date)) {
					authorization = tokenData.getString("token");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (StringUtils.isEmpty(authorization)) {
			Map<String, String> param = new HashMap<String, String>();
			param.put("clientId", FPayConfig.getClientId());
			param.put("clientSecret", FPayConfig.getClientSecret());
			param.put("grantType", FPayConfig.getGrantType());
			param.put("appId", FPayConfig.getAppId());
			String result = HttpURLRequestUtils.httpURLRequest(
					FPayConfig.getBaseUrl()+FPayConfig.getGetAuthorizationUrl(), 
					null, param, "utf-8");
			JSONObject response = JSONObject.parseObject(result);
			if ("0".equals(response.getString("code"))) {
				JSONObject data = response.getJSONObject("data");
				authorization = data.getString("access_token");
				JSONObject tokenData = new JSONObject();
				tokenData.put("token", authorization);
				tokenData.put("time", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
				configDataService.saveData("authorizationToken", tokenData.toJSONString());
			}
		}
		return authorization;
	}

	/**
	 * 统一下单
	 * @param orderNo 订单号
	 * @param title 订单标题
	 * @param amount 订单金额
	 * @return
	 */
	public static Map<String, Object> placeAnOrder(String orderNo, String title, int amount){
		log.info("调用聚合支付统一下单接口");
		String payAmount = FPayConfig.getPayAmount();
		if (StringUtils.isBlank(payAmount)) {
			payAmount = "0";
		}
		if (Integer.parseInt(payAmount)<=0) {
			payAmount = ""+amount;
		}
		
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.HOUR, 1);
		
		Map<String, Object> body = new HashMap<String, Object>();
		body.put("merNo", FPayConfig.getMerNo());
		body.put("outTransNo", orderNo);
		body.put("payType", "1000");
		body.put("amount", payAmount);
		body.put("summary", title);
		body.put("notifyUrl", WebAppConfigurer.getBaseUrl()+FPayConfig.getNotifyUrl());
		body.put("orderExpireTime", DateFormatUtils.format(calendar.getTime(), "yyyy-MM-dd HH:mm:ss"));
		/*List<Map<String, Object>> splitRules = new ArrayList<Map<String,Object>>();
		body.put("splitRule", splitRules);*/
		
		JSONObject param = new JSONObject();
		param.put("header", getHeader());
		param.put("body", body);
		
		Map<String, String> headrs = new HashMap<String, String>();
		headrs.put("Authorization", "Bearer "+getAuthorization(false));
		
		String result = HttpURLRequestUtils.httpURLRequest(
				FPayConfig.getBaseUrl()+FPayConfig.getPlaceAnOrderUrl(), 
				headrs, param.toJSONString(), "utf-8");
		
		return JSONObject.parseObject(result);
	}

	/**
	 * 退款
	 * @param outTransNo 原外部交易流水号（下单流水号）
	 * @param refundDesc 退款说明
	 * @param outRefundNo 外部系统退款流水号，外部系統保持唯一
	 * @param refundAmount 退款金额
	 * @return
	 */
	public static Map<String, Object> refund(String outTransNo, 
			String refundDesc, String outRefundNo, int refundAmount) {
		log.info("调用聚合支付退款接口");
		Map<String, Object> body = new HashMap<String, Object>();
		body.put("outTransNo", outTransNo);
		body.put("outRefundNo", outRefundNo);
		body.put("payType", "1000");
		body.put("refundAmount", ""+refundAmount);
		body.put("refundType", "0");
		//body.put("notifyUrl", FPayConfig.getNotifyUrl());
		body.put("refundDesc", refundDesc);
		
		JSONObject param = new JSONObject();
		param.put("header", getHeader());
		param.put("body", body);
		
		Map<String, String> headrs = new HashMap<String, String>();
		headrs.put("Authorization", "Bearer "+getAuthorization(false));
		
		String result = HttpURLRequestUtils.httpURLRequest(
				FPayConfig.getBaseUrl()+FPayConfig.getRefundUrl(), 
				headrs, param.toJSONString(), "utf-8");
		
		return JSONObject.parseObject(result);
	}

	/**
	 * 订单查询
	 * @param queryType 查询类型 1：订单交易 2：订单退款
	 * @param outTransNo 原外部交易流水号
	 * @return
	 */
	public static Map<String, Object> query(String queryType, String outTransNo) {
		log.info("调用聚合支付订单查询接口");
		Map<String, Object> body = new HashMap<String, Object>();
		body.put("queryType", queryType);
		body.put("outTransNo", outTransNo);
		
		JSONObject param = new JSONObject();
		param.put("header", getHeader());
		param.put("body", body);
		
		Map<String, String> headrs = new HashMap<String, String>();
		headrs.put("Authorization", "Bearer "+getAuthorization(false));
		
		String result = HttpURLRequestUtils.httpURLRequest(
				FPayConfig.getBaseUrl()+FPayConfig.getQueryUrl(), 
				headrs, param.toJSONString(), "utf-8");
		
		return JSONObject.parseObject(result);
	}

	/**
	 * 获取对账单下载URL
	 * @param accountDate 会计日期：格式为yyyy-MM-dd
	 * @return
	 */
	public static Map<String, Object> billDownloadUrl(String accountDate) {
		log.info("调用获取对账单下载URL接口");
		Map<String, Object> body = new HashMap<String, Object>();
		body.put("accountDate", accountDate);
		
		JSONObject param = new JSONObject();
		param.put("header", getHeader());
		param.put("body", body);
		
		Map<String, String> headrs = new HashMap<String, String>();
		headrs.put("Authorization", "Bearer "+getAuthorization(false));
		
		String result = HttpURLRequestUtils.httpURLRequest(
				FPayConfig.getBaseUrl()+FPayConfig.getBillDownloadUrl(), 
				headrs, param.toJSONString(), "utf-8");
		
		return JSONObject.parseObject(result);
	}
}
